home *** CD-ROM | disk | FTP | other *** search
- /*DrawingServant Version 0.1
-
- A utility program for putting a NeXT graphics head on a
- terminal based program. Since this is never intended to be
- a REAL NeXT application, many parts of an "official" application
- (i.e. Preferences, Help, language selection...) are omitted.
- This program is primarily intended to be forked from another process
- and communicated to through pipes. (Although you can invoke it
- directly and have yet another PS hacker's treat. Perhaps it is
- slightly easier to use than pft.)
- Comments, additions, subtractions are appreciated
- joe@ril3.tamri.com
- Copyright 1993 Joe Carlson
- Permission is granted for non-commercial reproduction and
- redistribution of this code provided this copyright notice
- remains.
- If you want to port some common program with this, drop me
- a note. I'll try to keep track of what is out there.
-
- This is IB free. The code is maybe slightly more amenable to hacking
- because of it.
- */
-
- #import <appkit/appkit.h>
- #import "DrawingServant.h"
-
- /* Default values for in and out pipes, x and y location
- and height and width of the window. Last number is initial
- size of PS code */
- #define DEFINPIPE 0
- #define DEFOUTPIPE 1
- #define DEFX 400.
- #define DEFY 250.
- #define DEFH 500.
- #define DEFW 500.
- #define MAXSTRINGSSTART 512
- static char *VERSIONID = "Drawing Servant Version 0.1\n";
- static char *ACKSTRING = "Ok\n";
-
- /* things for possible improvements and additions:
- 1) multiple windows
- 2) error handling
- 3) why do I need the gsave/grestore?
- */
-
- id DrawView;
- id DrawWindow;
- id myWindow, myMenu, windowText;
- id Panelview,myPanel;
-
- void setUp(argc,argv)
- int argc;
- char **argv;
- {
-
-
- NXRect aRect;
- int i;
-
- void *data;
- void iohandler();
-
- /* Set up a Panel */
-
- NXSetRect(&aRect, 150.0, 600.0, 300.0, 200.0);
- Panelview = [[InfoPanel alloc]init];
- [Panelview setOpaque:YES];
- myPanel = [[Panel alloc] initContent:&aRect
- style:NX_TITLEDSTYLE
- backing:NX_BUFFERED
- buttonMask:NX_CLOSEBUTTONMASK
- defer:YES];
- [myPanel setTitle:"About Drawing Servant"];
- [myPanel setContentView:Panelview];
-
- /* set up the drawing window */
- DrawView = [[Drawclass alloc] init];
- [DrawView commandlineargs:argc:argv];
- [DrawView setOpaque:YES];
- DrawWindow = [[Window alloc]initContent:[DrawView viewbox:nil]
- style:NX_TITLEDSTYLE
- backing:NX_BUFFERED
- buttonMask:NX_CLOSEBUTTONMASK
- defer:NO];
-
- [DrawWindow setTitle:"Drawing Servant"];
- [DrawWindow setContentView:DrawView];
- [DrawWindow orderFront:nil];
- [DrawWindow display];
- [DrawView mouseoff:nil];
- [DrawView ackon:nil];
- [DrawView expandstringarea:MAXSTRINGSSTART From:0];
- [[DrawView window]addToEventMask: NX_RMOUSEDOWNMASK];
-
-
- /* Set up a Menu */
- myMenu = [[Menu alloc] initTitle:"Drawing Servant"];
- [[myMenu addItem:"Info..."
- action:@selector(orderFront:)
- keyEquivalent:'\0']
- setTarget:myPanel];
- /* gee...I'd like to get this working next... */
- /*[[myMenu addItem:"New"
- action:@selector(newview:)
- keyEquivalent:'n']
- setTarget:DrawView];*/
- [[myMenu addItem:"Clear"
- action:@selector(clearview:)
- keyEquivalent:'c']
- setTarget:DrawView];
- [[myMenu addItem:"Save"
- action:@selector(saveview:)
- keyEquivalent:'s']
- setTarget:DrawView];
- [[myMenu addItem:"Print"
- action:@selector(printview:)
- keyEquivalent:'p']
- setTarget:DrawView];
- [myMenu addItem:"Hide"
- action:@selector(hide:)
- keyEquivalent:'h'];
- [myMenu addItem:"Quit"
- action:@selector(terminate:)
- keyEquivalent:'q'];
- [myMenu sizeToFit];
- [NXApp setMainMenu:myMenu];
-
-
- /* prepare to interrupt on input */
- DPSAddFD([DrawView inpipe:nil],iohandler,data,NX_BASETHRESHOLD);
-
- return;
- }
- void
- iohandler(fd,data)
- int fd;
- void *data;
- {
-
- char string[BUFSIZ];
- int i;
- void processcommand();
-
- read([DrawView inpipe:nil],string,sizeof(string)-1);
-
- /* just make sure we are terminated */
- for(i=0;i<strlen(string);i++) {
- if(string[i]=='\n' || string[i]==0){
- string[i]='\n';
- /* zero out the rest, just to be safe... */
- for(i++;i<strlen(string);string[i++]=0);
- break;
- }
- }
-
- processcommand(string);
- }
-
- processcommand(string)
- char *string;
- {
- if(!strncmp(string,"DSversion",9) ) {
- write([DrawView outpipe:nil],VERSIONID,strlen(VERSIONID));
-
- } else if (!strncmp(string,"DSclear",7) ) {
- [DrawView clearview:nil];
-
- } else if (!strncmp(string,"DSsave",6) ) {
- [DrawView saveview:nil];
-
- } else if (!strncmp(string,"DSoops",6) ) {
- [DrawView subfromstrings:string];
-
- } else if (!strncmp(string,"DSprint",7) ) {
- [DrawView printview:nil];
-
- } else if (!strncmp(string,"DSmouseon",9) ) {
- [DrawView mouseon:nil];
-
- } else if (!strncmp(string,"DSmouseoff",10) ) {
- [DrawView mouseoff:nil];
-
- } else if (!strncmp(string,"DSackon",7) ) {
- [DrawView ackon:nil];
-
- } else if (!strncmp(string,"DSackoff",8) ) {
- [DrawView ackoff:nil];
-
- } else if (!strncmp(string,"DSfront",7) ) {
- [[DrawView window] orderFrontRegardless];
-
- } else if (!strncmp(string,"DShide",6) ) {
- [NXApp hide:nil];
-
- } else if (!strncmp(string,"DSquit",6) ) {
- [NXApp terminate:nil];
-
- } else {
- [DrawView addtostrings:string];
- }
- /* 'S alright? */
- if([DrawView isackon:nil])
- write([DrawView outpipe:nil],ACKSTRING,strlen(ACKSTRING));
-
- }
-
- @implementation Drawclass
- -drawSelf: (NXRect *)rects: (int)rectCount;
- {
- int i;
-
- /* just clear the screen */
- if(needtoclear) {
- PSsetgray(NX_WHITE);
- PSrectfill(bounds.origin.x,bounds.origin.y,
- bounds.size.width,bounds.size.height);
- PSsetgray(NX_BLACK);
- needtoclear = NO;
- /* just write the last string to the window server */
- } else if(justlast) {
- if(nstrings) {
- /* can someone tell me why the save/restore is needed?*/
- PSgrestore();
- DPSPrintf(DPSGetCurrentContext(),
- "%s \n",psstrings[nstrings-1]);
- PSgsave();
- }
- /* the whole thing */
- } else {
- for(i=0;i<nstrings;) {
- DPSPrintf(DPSGetCurrentContext(),"%s \n",psstrings[i++]);
- }
- }
- return self;
- }
- -addtostrings:(char *)string;
- {
- /* if we got too many strings, allocate space for more */
- if(nstrings==maxstrings)
- [self expandstringarea:2*maxstrings From:maxstrings];
-
- psstrings[nstrings] = malloc(strlen(string)+1);
- strcpy(psstrings[nstrings++],string);
-
- /* when the string is added to the list, we just need to
- update the screen with the last line */
- justlast = YES;
- [self display];
-
- /* otherwise (for printing or saving) we'll want to send to
- entire list of postscript commands */
- justlast = NO;
- return;
- }
- -subfromstrings:(char *)string;
- {
- /* remove the last */
- if(nstrings)
- free(psstrings[--nstrings]);
- /*redraw all the ps code */
- justlast = NO;
- [self display];
- }
- -clearview:sender;
- {
- for(;nstrings;) {
- free(psstrings[--nstrings]);
- }
- needtoclear = YES;
- [self display];
- return self;
- }
- -saveview:sender;
- {
- id save;
- save = [[SavePanel new]
- setRequiredFileType:"eps"];
-
- if ([save runModal]==1) {
- NXStream *aStream;
- aStream = NXOpenMemory(0,0,NX_WRITEONLY);
- [self copyPSToStream:aStream forView:self];
- NXSaveToFile(aStream, [save filename]);
- NXCloseMemory(aStream, NX_FREEBUFFER);
- }
- return self;
- }
- -copyPSToStream:(NXStream *)aStream forView:view;
- {
- NXRect boundingbox;
-
- [view getBounds:&boundingbox];
- [view copyPSCodeInside:&boundingbox to:aStream];
- return self;
- }
- -printview:sender
- {
- [self printPSCode:nil];
- return self;
- }
- -(int)inpipe:sender
- {
- return inpipenumber;
- }
- -(int)outpipe:sender
- {
- return outpipenumber;
- }
- -(NXRect *)viewbox:sender
- {
- return &windowrectangle;
- }
- -expandstringarea:(int)to From:(int)from
- {
- char **temp;
- int i;
-
- temp = (char **) malloc(to*sizeof(char *));
- for(i=0;i<from;i++) {
- temp[i] = psstrings[i];
- }
- if(from)
- free(psstrings);
- psstrings = temp;
- maxstrings = to;
- return;
- }
- -mouseon:sender
- {
- printmouseclicks = YES;
- return self;
- }
- -mouseoff:sender
- {
- printmouseclicks = NO;
- return self;
- }
- -mouseDown:(NXEvent *)theEvent
- {
- char string[80];
-
- if(printmouseclicks) {
- sprintf(string,"left mouse %f %f\n",
- theEvent->location.x,theEvent->location.y);
- write([DrawView outpipe:nil],string,strlen(string));
- }
- return;
-
- return self;
- }
- -rightMouseDown:(NXEvent *)theEvent
- {
- char string[80];
-
- if(printmouseclicks) {
- sprintf(string,"right mouse %f %f\n",
- theEvent->location.x,theEvent->location.y);
- write([DrawView outpipe:nil],string,strlen(string));
- }
- return;
-
- return self;
- }
-
- -ackon:sender
- {
- sendackstring = YES;
- return self;
- }
- -ackoff:sender
- {
- sendackstring = NO;
- return self;
- }
- -(BOOL)isackon:sender
- {
- if(sendackstring)
- return YES;
- else
- return NO;
- }
- -commandlineargs: (int)argc: (char **)argv;
- /* process the command line arguments. Nothing fancy here, just
- plow through things. - signs before args are not required.*/
- {
- int i;
-
- /* reasonable guesses for things like in and outpipes,
- height width and placement */
- height = DEFH;
- width = DEFW;
- xoffset = DEFX;
- yoffset = DEFY;
- inpipenumber = DEFINPIPE;
- outpipenumber = DEFOUTPIPE;
- for(i=1;i<argc;) {
- /* strip off tabs and blanks */
- for(;argv[i][0]==' ' || argv[i][0]==' ';)
- strcpy(argv[i],argv[i]+1);
- /* perhaps arguments have a - in front; or maybe not.
- we are processing everything as a switch, strip off the - */
- if(argv[i][0]=='-')
- strcpy(argv[i],argv[i]+1);
- switch (argv[i][0]) {
- case 'h': case 'H':
- if(argv[i][1]==0){
- if(++i==argc)
- break;
- height = atof(argv[i]);
- } else {
- height = atof(argv[i]+1);
- }
- i++;
- break;
- case 'w': case 'W':
- if(argv[i][1]==0) {
- if(++i==argc)
- break;
- width = atof(argv[i]);
- } else {
- width = atof(argv[i]+1);
- }
- i++;
- break;
- case 'x': case 'X':
- if(argv[i][1]==0) {
- if(++i==argc)
- break;
- xoffset = atof(argv[i]);
- } else {
- xoffset = atof(argv[i]+1);
- }
- i++;
- break;
- case 'y': case 'Y':
- if(argv[i][1]==0) {
- if(++i==argc)
- break;
- yoffset = atof(argv[i]);
- } else {
- yoffset = atof(argv[i]+1);
- }
- i++;
- break;
- case 'i': case 'I':
- if(argv[i][1]==0) {
- if(++i==argc)
- break;
- inpipenumber=atoi(argv[i]);
- } else {
- inpipenumber=atoi(argv[i]+1);
- }
- i++;
- break;
- case 'o': case 'O':
- if(argv[i][1]==0) {
- if(++i==argc)
- break;
- outpipenumber=atoi(argv[i]);
- } else {
- outpipenumber=atoi(argv[i]+1);
- }
- i++;
- break;
- default:
- i++;
- }
- }
-
- NXSetRect([self viewbox:nil],xoffset,yoffset,width,height);
- }
- @end
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- [Application new];
- setUp(argc,argv);
- [NXApp run];
- [NXApp free];
- }
- @implementation InfoPanel
- -drawSelf: (NXRect *)rects: (int) rectCount;
- {
- NXRect aRect;
- DPSTimedEntryProc melter();
-
- NXSetRect(&aRect,0.,0., 300.0, 200.0);
- PSsetgray(NX_WHITE);
- PSrectfill(bounds.origin.x,bounds.origin.y,
- bounds.size.width,bounds.size.height);
- PSsetgray(NX_BLACK);
- PSmoveto(45.,150.);
- PSselectfont("Times-Roman",20.);
- PSshow(VERSIONID);
-
- PSselectfont("Times-Roman",12.);
- PSmoveto(45.,100.);
- PSshow("Copyright 1993 by J Carlson");
- PSmoveto(45.,85.);
- PSshow("Permission is granted for noncommercial");
- PSmoveto(45.,70.);
- PSshow("Redistribution of this program");
- PSmoveto(45.,55.);
- PSshow("Provided this copyright notice stays intact.");
-
- return self;
- }
- @end
-